from string import ascii_lowercase
import sys
from bisect import bisect_right, bisect_left
import os
import sys
from io import BytesIO, IOBase
from math import factorial, floor, sqrt, inf, ceil, gcd
from collections import defaultdict, deque, Counter
from functools import cmp_to_key
BUFSIZE = 8192
class FastIO(IOBase):
newlines = 0
def __init__(self, file):
self._fd = file.fileno()
self.buffer = BytesIO()
self.writable = "x" in file.mode or "r" not in file.mode
self.write = self.buffer.write if self.writable else None
def read(self):
while True:
b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
if not b:
break
ptr = self.buffer.tell()
self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
self.newlines = 0
return self.buffer.read()
def readline(self):
while self.newlines == 0:
b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
self.newlines = b.count(b"\n") + (not b)
ptr = self.buffer.tell()
self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
self.newlines -= 1
return self.buffer.readline()
def flush(self):
if self.writable:
os.write(self._fd, self.buffer.getvalue())
self.buffer.truncate(0), self.buffer.seek(0)
class IOWrapper(IOBase):
def __init__(self, file):
self.buffer = FastIO(file)
self.flush = self.buffer.flush
self.writable = self.buffer.writable
self.write = lambda s: self.buffer.write(s.encode("ascii"))
self.read = lambda: self.buffer.read().decode("ascii")
self.readline = lambda: self.buffer.readline().decode("ascii")
sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip("\r\n")
def inp():
return(int(input()))
def inlt():
return(list(map(int,input().split())))
def insr():
s = input()
return(s[:len(s) - 1])
def invr():
return(map(int,input().split()))
def insr2():
s = input()
return(s.split(" "))
def build_mod_inverses(n, r, p):
fact = [1] * (n + 1)
for i in range(1, n + 1):
fact[i] = i * fact[i - 1] % p
inv = [1] * (n + 1)
inv[n] = pow(fact[n], p - 2, p)
for i in range(n - 1, -1, -1):
inv[i] = (i + 1) * inv[i + 1] % p
return fact, inv
def comb(n, r, p, fact, inv):
return fact[n] * inv[r] % p * inv[n - r] % p if n >= r >= 0 else 0
def make_divisors(n):
divisors = []
for i in range(1, int(n**0.5)+1):
if n % i == 0:
divisors.append(i)
if i != n // i and i != 1:
divisors.append(n // i)
return divisors
def dfs(graph, vertex):
visited = set()
tree = []
deq = deque([vertex])
while deq:
vertex = deq.pop()
if vertex not in visited:
visited.add(vertex)
deq.extend(graph[vertex])
tree.append(vertex)
return tree
def find_in_sorted_list(elem, sorted_list):
'Locate the leftmost value exactly equal to x'
i = bisect_left(sorted_list, elem)
if i != len(sorted_list) and sorted_list[i] == elem:
return i
return -1
class SegmentTree:
def __init__(self, data, default=0, func=lambda a, b: a+b):
self._default = default
self._func = func
self._len = len(data)
self._size = _size = 1 << (self._len - 1).bit_length()
self.data = [default] * (2 * _size)
self.data[_size:_size + self._len] = data
for i in reversed(range(_size)):
self.data[i] = func(self.data[i + i], self.data[i + i + 1])
def __delitem__(self, idx):
self[idx] = self._default
def __getitem__(self, idx):
return self.data[idx + self._size]
def __setitem__(self, idx, value):
idx += self._size
self.data[idx] = value
idx >>= 1
while idx:
self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
idx >>= 1
def __len__(self):
return self._len
def query(self, start, stop):
if start == stop:
return self.__getitem__(start)
start += self._size
stop += self._size
res = self._default
while start < stop:
if start & 1:
res = self._func(res, self.data[start])
start += 1
if stop & 1:
stop -= 1
res = self._func(res, self.data[stop])
start >>= 1
stop >>= 1
return res
def __repr__(self):
return "SegmentTree({0})".format(self.data)
n = inp()
graph = defaultdict(list)
for i in range(n):
s = input().strip()
if len(s) == 1:
graph[s[0]] = []
else:
for j in range(1, len(s)):
if s[j-1] not in graph[s[j]]:
graph[s[j]].append(s[j-1])
graph[s[j-1]].append(s[j])
seen = set()
ans = 0
for letter in graph.keys():
if letter in seen:
continue
ans += 1
seen.add(letter)
deq = deque([letter])
while deq:
l = deq.pop()
for l2 in graph[l]:
if l2 in seen:
continue
seen.add(l2)
deq.append(l2)
print(ans)
#include <bits/stdc++.h>
using namespace std;
#define f(i, a, b) for (ll i = a; i < b; i++)
#define fr(i, a, b) for (ll i = b - 1; i >= a; i--)
#define fa(x) for (auto ele : x)
#define all(x) (x).begin(), (x).end()
#define ll long long
#define db double
#define pii pair<int, int>
#define pll pair<ll, ll>
#define ppiii pair<pair<int, int>, int>
#define vi vector<int>
#define vl vector<ll>
#define vb vector<bool>
#define vs vector<string>
#define v(ele) vector<ele>
#define sei set<int>
#define sel set<ll>
#define ses set<string>
#define sec set<char>
#define se(ele) set<ele>
#define mii map<int, int>
#define mll map<ll, ll>
#define mp(e1, e2) map<e1, e2>
#define mipii map<int, pii>
#define mcpii map<char, pii>
#define mcpci map<char, pair<char, int>>
#define mpiii map<pair<char, int>, int>
#define mic map<int, char>
#define mci map<char, int>
#define mcsei map<char, sei>
#define mlsel map<ll, sel>
#define mcvi map<char, vi>
#define mci map<char, int>
#define msi map<string, int>
#define misei map<int, sei>
#define mlvl map<ll, vl>
#define mivi map<int, vi>
#define mlpll map<ll, pll>
#define mplll map<pll, ll>
#define qi queue<int>
#define ql queue<ll>
#define qpii queue<pair<int, int>>
const ll mod = 1e9 + 7;
const ll INF = 1e16;
const ll NEG_INF = LONG_LONG_MIN;
const ll N = 2e5 + 5;
// const int N = 7;
sei g[N];
bool vis[N];
void dfs(int ver)
{
vis[ver] = 1;
fa(g[ver])
{
if (!vis[ele])
{
dfs(ele);
}
}
}
void solve()
{
int n;
cin >> n;
string s1;
int len;
sec hs;
vi ch_v[26];
f(i, 0, n)
{
cin >> s1;
len = s1.length();
f(j, 0, len)
{
if (!ch_v[s1[j] - 'a'].empty())
{
g[ch_v[s1[j] - 'a'].back()].insert(i);
g[i].insert(ch_v[s1[j] - 'a'].back());
}
ch_v[s1[j] - 'a'].push_back(i);
}
}
int ans = 0;
f(i, 0, n)
{
if (!vis[i])
{
dfs(i);
ans++;
}
}
cout << ans << '\n';
return;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}
318. Maximum Product of Word Lengths | 448. Find All Numbers Disappeared in an Array |
1155. Number of Dice Rolls With Target Sum | 415. Add Strings |
22. Generate Parentheses | 13. Roman to Integer |
2. Add Two Numbers | 515. Find Largest Value in Each Tree Row |
345. Reverse Vowels of a String | 628. Maximum Product of Three Numbers |
1526A - Mean Inequality | 1526B - I Hate 1111 |
1881. Maximum Value after Insertion | 237. Delete Node in a Linked List |
27. Remove Element | 39. Combination Sum |
378. Kth Smallest Element in a Sorted Matrix | 162. Find Peak Element |
1529A - Eshag Loves Big Arrays | 19. Remove Nth Node From End of List |
925. Long Pressed Name | 1051. Height Checker |
695. Max Area of Island | 402. Remove K Digits |
97. Interleaving String | 543. Diameter of Binary Tree |
124. Binary Tree Maximum Path Sum | 1465. Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts |
501A - Contest | 160A- Twins |